#include "DungeonGenerator.hh"
#include "Enemy.hh"
#include "Accessory.hh"
#include <ctime>
#include <algorithm>
#include <random>

namespace DungeonRPG {

std::vector<Room*> DungeonGenerator::generateDungeon(int maxRooms, int width, int height) {
    // Seed RNG for consistent randomness
    std::srand(static_cast<unsigned>(std::time(nullptr)));

    std::vector<Room*> rooms;
    std::map<std::pair<int, int>, Room*> roomGrid;

    // Possible movement directions
    std::vector<std::pair<int, int>> directions = {
        {1, 0}, {-1, 0}, {0, 1}, {0, -1}
    };

    // Start from center of map
    int x = width / 2;
    int y = height / 2;
    roomGrid[{x, y}] = new Room("Start", "The start of your adventure.");
    rooms.push_back(roomGrid[{x, y}]);

    // Rooms to expand from
    std::vector<std::pair<int, int>> frontier = {{x, y}};

    // Expand dungeon by growing from frontier
    while (rooms.size() < (size_t)maxRooms && !frontier.empty()) {
        auto [cx, cy] = frontier.back();
        frontier.pop_back();

        // Shuffle directions to vary map layout
        std::shuffle(directions.begin(), directions.end(), std::default_random_engine(std::rand()));

        for (auto [dx, dy] : directions) {
            int nx = cx + dx;
            int ny = cy + dy;

            // Check bounds and ensure new room isn't overlapping
            if (roomGrid.count({nx, ny}) == 0 && nx >= 0 && nx < width && ny >= 0 && ny < height) {
                Room* newRoom = new Room("Room", "A mysterious chamber.");
                roomGrid[{nx, ny}] = newRoom;
                rooms.push_back(newRoom);
                frontier.push_back({nx, ny});

                // Link new room and current room bidirectionally
                roomGrid[{cx, cy}]->addConnection(
                    dx == 1 ? "east" : dx == -1 ? "west" : dy == 1 ? "north" : "south",
                    newRoom);
                newRoom->addConnection(
                    dx == 1 ? "west" : dx == -1 ? "east" : dy == 1 ? "south" : "north",
                    roomGrid[{cx, cy}]);

                // Stop if max room limit reached
                if (rooms.size() >= (size_t)maxRooms) break;
            }
        }
    }

    return rooms;
}

}
